package com.server.commons.huawei_obs.base;

import cn.hutool.core.io.IoUtil;
import com.obs.services.ObsClient;
import com.obs.services.model.*;
import com.server.model.all.enums.BucketNameEnum;
import com.server.common.code.error.BusinessException;
import com.server.commons.file.base.BaseFile;
import com.server.commons.file.interfaces.FileFactoryInterface;
import com.server.commons.file.model.input.UploadFileInput;
import com.server.commons.file.model.output.UploadFileOutput;
import com.server.commons.huawei_obs.config.HuaweiOBSConfig;
import com.server.commons.huawei_obs.enums.HuaweiOBSLocationEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;

/**
 * 文档-https://support.huaweicloud.com/perms-cfg-obs/obs_40_0041.html
 * @author LXC
 * @date 2023/2/9 16:11
 */
@Component
@Slf4j
public abstract class BaseHuaweiOBSFile extends BaseFile {

    @Resource
    private HuaweiOBSConfig huaweiOBSConfig;

    @Resource
    private FileFactoryInterface fileFactoryInterface;

    private ObsClient obsClient;

    //获取区域
    public abstract HuaweiOBSLocationEnum getHuaweiOBSLocationEnum();

    //启动时加入到工程中
    @PostConstruct
    public void init() {
        fileFactoryInterface.register(getBucketNameEnum(),this);
        obsClient = new ObsClient(huaweiOBSConfig.getAccessKey(),huaweiOBSConfig.getSecretKey(),getHuaweiOBSLocationEnum().getEndPoint());
    }

    //销毁前
    @PreDestroy
    public void destroy(){
        try {
            obsClient.close();
        } catch (IOException e) {
            log.error("华为OBS关闭成功",e);
        }
    }

    @Override
    public UploadFileOutput uploadFile(UploadFileInput uploadFileInput) {
        UploadFileOutput uploadFileOutput =  super.uploadFile(uploadFileInput);
        String bucketName = getBucketNameEnum().getName();
        String path = uploadFileInput.getPath();
        HuaweiOBSLocationEnum huaweiOBSLocationEnum = getHuaweiOBSLocationEnum();

        try (InputStream inputStream = IoUtil.toStream(uploadFileInput.getBytes())){
            //创建桶
            if(!obsClient.headBucket(bucketName)){
                ObsBucket obsBucket = new ObsBucket();
                obsBucket.setLocation(huaweiOBSLocationEnum.getLocation());
                obsBucket.setBucketName(bucketName);
                obsClient.createBucket(bucketName,huaweiOBSLocationEnum.getLocation());

                if(!ObjectUtils.isEmpty(getPolicy())){
                    SetBucketPolicyRequest setBucketPolicyRequest = new SetBucketPolicyRequest();
                    setBucketPolicyRequest.setBucketName(bucketName);
                    setBucketPolicyRequest.setPolicy(getPolicy());
                    obsClient.setBucketPolicy(setBucketPolicyRequest);
                }

            }

            //上传
            PutObjectRequest putObjectRequest = new PutObjectRequest();
            putObjectRequest.setObjectKey(path);
            putObjectRequest.setBucketName(bucketName);
            putObjectRequest.setInput(inputStream);
            obsClient.putObject(putObjectRequest);

            return uploadFileOutput;
        } catch (Exception e) {
            log.error("uploadFile-",e);
        }
        throw new BusinessException("上传文件失败");
    }


    @Override
    public byte[] downFile(String paths) {
        String bucketName = getBucketNameEnum().getName();
        paths = paths.substring(bucketName.length()+1);

        try (InputStream inputStream = obsClient.getObject(new GetObjectRequest(bucketName, paths)).getObjectContent();) {
            return IoUtil.readBytes(inputStream);
        } catch (IOException e) {
            log.error("下载失败",e);
        }
        throw new BusinessException("下载文件失败");
    }

    @Override
    public Boolean deleteFile(String paths) {
        try {
            String bucketName = getBucketNameEnum().getName();
            paths = paths.substring(bucketName.length()+1);
            DeleteObjectResult deleteObjectResult = obsClient.deleteObject(bucketName, paths);
            return deleteObjectResult.isDeleteMarker();
        }catch (Exception e){
            log.error("删除失败",e);
        }
        throw new BusinessException("删除文件失败");
    }

    @Override
    public Long getSize(String bucketName, String paths) {
        try {
            return obsClient.getObject(bucketName,paths).getMetadata().getContentLength();
        }catch (Exception e){
            log.error("获取大小",e);
        }
        throw new BusinessException("获取文件大小失败");
    }

    @Override
    public String getShareUrl(String paths, int duration) {
        TemporarySignatureRequest request = new TemporarySignatureRequest(HttpMethodEnum.GET, duration);
        //设置桶名,一般都是写在配置里，这里直接赋值即可
        request.setBucketName(getBucketNameEnum().getName());
        //这里相当于设置你上传到obs的文件路
        request.setObjectKey(paths);
        TemporarySignatureResponse temporarySignature = obsClient.createTemporarySignature(request);
        return BucketNameEnum.getBucketNameEnum(getBucketNameEnum().getName()).getMapperNgName() + "/" + temporarySignature.getSignedUrl();
    }
}
